home *** CD-ROM | disk | FTP | other *** search
- ; RECEIVE.ASM
- ;
- ; This program is the receiver portion of the programs that transmit files
- ; across a Laplink compatible parallel cable.
- ;
- ; This program assumes that the user want to use LPT1: for transmission.
- ; Adjust the equates, or read the port from the command line if this
- ; is inappropriate.
-
- .286
- .xlist
- include stdlib.a
- includelib stdlib.lib
- .list
-
-
- dseg segment para public 'data'
-
- TimeOutConst equ 100 ;About 1 min on 66Mhz 486.
- PrtrBase equ 8 ;Offset to LPT1: adrs.
-
- MyPortAdrs word ? ;Holds printer port address.
- FileHandle word ? ;Handle for output file.
- FileBuffer byte 512 dup (?) ;Buffer for incoming data.
-
- FileSize dword ? ;Size of incoming file.
- FileName byte 128 dup (0) ;Holds filename
-
- dseg ends
-
- cseg segment para public 'code'
- assume cs:cseg, ds:dseg
-
-
- ; TestAbort- Reads the keyboard and gives the user the opportunity to
- ; hit the ctrl-C key.
-
- TestAbort proc near
- push ax
- mov ah, 1
- int 16h ;See if keypress.
- je NoKeypress
- mov ah, 8 ;Read char, chk for ctrl-C
- int 21h
- NoKeyPress: pop ax
- ret
- TestAbort endp
-
-
-
- ; GetByte- Reads a single byte from the parallel port (four bits at
- ; at time). Returns the byte in AL.
-
- GetByte proc near
- push cx
- push dx
-
- ; Receive the L.O. Nibble.
-
- mov dx, MyPortAdrs
- mov al, 10h ;Signal not busy.
- out dx, al
-
- inc dx ;Point at status port
-
- W4DLp: mov cx, 10000
- Wait4Data: in al, dx ;See if data available.
- test al, 80h ; (bit 7=0 if data available).
- loopne Wait4Data
- je DataIsAvail ;Is data available?
- call TestAbort ;If not, check for ctrl-C.
- jmp W4DLp
-
- DataIsAvail: shr al, 3 ;Save this four bit package
- and al, 0Fh ; (This is the L.O. nibble
- mov ah, al ; for our byte).
-
- dec dx ;Point at data register.
- mov al, 0 ;Signal data taken.
- out dx, al
-
- inc dx ;Point at status register.
- W4ALp: mov cx, 10000
- Wait4Ack: in al, dx ;Wait for transmitter to
- test al, 80h ; retract data available.
- loope Wait4Ack ;Loop until data not avail.
- jne NextNibble ;Branch if data not avail.
- call TestAbort ;Let user hit ctrl-C.
- jmp W4ALp
-
- ; Receive the H.O. nibble:
-
- NextNibble: dec dx ;Point at data register.
- mov al, 10h ;Signal not busy
- out dx, al
- inc dx ;Point at status port
- W4D2Lp: mov cx, 10000
- Wait4Data2: in al, dx ;See if data available.
- test al, 80h ; (bit 7=0 if data available).
- loopne Wait4Data2 ;Loop until data available.
- je DataAvail2 ;Branch if data available.
- call TestAbort ;Check for ctrl-C.
- jmp W4D2Lp
-
- DataAvail2: shl al, 1 ;Merge this H.O. nibble
- and al, 0F0h ; with the existing L.O.
- or ah, al ; nibble.
- dec dx ;Point at data register.
- mov al, 0 ;Signal data taken.
- out dx, al
-
- inc dx ;Point at status register.
- W4A2Lp: mov cx, 10000
- Wait4Ack2: in al, dx ;Wait for transmitter to
- test al, 80h ; retract data available.
- loope Wait4Ack2 ;Wait for data not available.
- jne ReturnData ;Branch if ack.
- call TestAbort ;Check for ctrl-C
- jmp W4A2Lp
-
- ReturnData: mov al, ah ;Put data in al.
- pop dx
- pop cx
- ret
- GetByte endp
-
-
-
-
- ; Synchronize- This procedure waits until it sees all zeros on the input
- ; bits we receive from the transmiting site. Once it receives
- ; all zeros, it writes all ones to the output port. When
- ; all ones come back, it writes all zeros. It repeats this
- ; process until the transmiting site writes the value 05h.
-
- Synchronize proc near
-
- print
- byte "Synchronizing with transmitter program"
- byte cr,lf,0
-
- mov dx, MyPortAdrs
- mov al, 0 ;Initialize our output port
- out dx, al ; to prevent confusion.
- mov bx, TimeOutConst ;Time out condition.
- SyncLoop: mov cx, 0 ;For time out purposes.
- SyncLoop0: inc dx ;Point at input port.
- in al, dx ;Read our input bits.
- dec dx
- and al, 78h ;Keep only the data bits.
- cmp al, 78h ;Check for all ones.
- je Got1s ;Branch if all ones.
- cmp al, 0 ;See if all zeros.
- loopne SyncLoop0
-
- ; Since we just saw a zero, write all ones to the output port.
-
- mov al, 0FFh ;Write all ones
- out dx, al
-
- ; Now wait for all ones to arrive from the transmiting site.
-
- SyncLoop1: inc dx ;Point at status register.
- in al, dx ;Read status port.
- dec dx ;Point back at data register.
- and al, 78h ;Keep only the data bits.
- cmp al, 78h ;Are they all ones?
- loopne SyncLoop1 ;Repeat while not ones.
- je Got1s ;Branch if got ones.
-
- ; If we've timed out, check to see if the user has pressed ctrl-C to
- ; abort.
-
- call TestAbort ;Check for ctrl-C.
- dec bx ;See if we've timed out.
- jne SyncLoop ;Repeat if time-out.
-
- print
- byte "Receive: connection timed out during synchronization"
- byte cr,lf,0
- clc ;Signal time-out.
- ret
-
- ; Jump down here once we've seen both a zero and a one. Send the two
- ; in combinations until we get a 05h from the transmiting site or the
- ; user presses Ctrl-C.
-
- Got1s: inc dx ;Point at status register.
- in al, dx ;Just copy whatever appears
- dec dx ; in our input port to the
- shr al, 3 ; output port until the
- and al, 0Fh ; transmiting site sends
- cmp al, 05h ; us the value 05h
- je Synchronized
- not al ;Keep inverting what we get
- out dx, al ; and send it to xmitter.
- call TestAbort ;Check for CTRL-C here.
- jmp Got1s
-
-
- ; Okay, we're synchronized. Return to the caller.
-
- Synchronized:
- and al, 0Fh ;Make sure busy bit is one
- out dx, al ; (bit 4=0 for busy=1).
- print
- byte "Synchronized with transmiting site"
- byte cr,lf,0
- stc
- ret
- Synchronize endp
-
-
- ; GetFileInfo- The transmitting program sends us the file length and a
- ; zero terminated filename. Get that data here.
-
- GetFileInfo proc near
- mov dx, MyPortAdrs
- mov al, 10h ;Set busy bit to zero.
- out dx, al ;Tell xmit pgm, we're ready.
-
- ; First four bytes contain the filesize:
-
- call GetByte
- mov byte ptr FileSize, al
- call GetByte
- mov byte ptr FileSize+1, al
- call GetByte
- mov byte ptr FileSize+2, al
- call GetByte
- mov byte ptr FileSize+3, al
-
- ; The next n bytes (up to a zero terminating byte) contain the filename:
-
- mov bx, 0
- GetFileName: call GetByte
- mov FileName[bx], al
- call TestAbort
- inc bx
- cmp al, 0
- jne GetFileName
-
- ret
- GetFileInfo endp
-
-
- ; GetFileData- Receives the file data from the transmitting site
- ; and writes it to the output file.
-
- GetFileData proc near
-
- ; First, see if we have more than 512 bytes left to go
-
- cmp word ptr FileSize+2, 0 ;If H.O. word is not
- jne MoreThan512 ; zero, more than 512.
- cmp word ptr FileSize, 512 ;If H.O. is zero, just
- jbe LastBlock ; check L.O. word.
-
- ; We've got more than 512 bytes left to go in this file, read 512 bytes
- ; at this point.
-
- MoreThan512: mov cx, 512 ;Receive 512 bytes
- lea bx, FileBuffer ; from the xmitter.
- ReadLoop: call GetByte ;Read a byte.
- mov [bx], al ;Save the byte away.
- inc bx ;Move on to next
- loop ReadLoop ; buffer element.
-
- ; Okay, write the data to the file:
-
- mov ah, 40h ;DOS write opcode.
- mov bx, FileHandle ;Write to this file.
- mov cx, 512 ;Write 512 bytes.
- lea dx, Filebuffer ;From this address.
- int 21h
- jc BadWrite ;Quit if error.
-
- ; Decrement the file size by 512 bytes:
-
- sub word ptr FileSize, 512 ;32-bit subtraction
- sbb word ptr FileSize, 0 ; of 512.
- jmp GetFileData
-
- ; Process the last block, that contains 1..511 bytes, here.
-
- LastBlock:
- mov cx, word ptr FileSize ;Receive the last
- lea bx, FileBuffer ; 1..511 bytes from
- ReadLB: call GetByte ; the transmitter.
- mov [bx], al
- inc bx
- loop ReadLB
-
- mov ah, 40h ;Write the last block
- mov bx, FileHandle ; of bytes to the
- mov cx, word ptr FileSize ; file.
- lea dx, Filebuffer
- int 21h
- jnc Closefile
-
- BadWrite: print
- byte "DOS error #",0
- puti
- print
- byte " while writing data.",cr,lf,0
-
- ; Close the file here.
-
- CloseFile: mov bx, FileHandle ;Close this file.
- mov ah, 3Eh ;DOS close opcode.
- int 21h
- ret
- GetFileData endp
-
-
-
- ; Here's the main program that gets the whole ball rolling.
-
- Main proc
- mov ax, dseg
- mov ds, ax
- meminit
-
-
- ; First, get the address of LPT1: from the BIOS variables area.
-
- mov ax, 40h ;Point at BIOS variable segment.
- mov es, ax
- mov ax, es:[PrtrBase]
- mov MyPortAdrs, ax
-
- call Synchronize ;Wait for the transmitter program.
- jnc Quit
-
- call GetFileInfo ;Get file name and size.
-
- printf
- byte "Filename: %s\nFile size: %ld\n",0
- dword Filename, FileSize
-
- mov ah, 3Ch ;Create file.
- mov cx, 0 ;Standard attributes
- lea dx, Filename
- int 21h
- jnc GoodOpen
- print
- byte "Error opening file",cr,lf,0
- jmp Quit
-
- GoodOpen: mov FileHandle, ax
- call GetFileData ;Get the file's data.
-
- Quit: ExitPgm ;DOS macro to quit program.
- Main endp
-
- cseg ends
-
- sseg segment para stack 'stack'
- stk byte 1024 dup ("stack ")
- sseg ends
-
- zzzzzzseg segment para public 'zzzzzz'
- LastBytes byte 16 dup (?)
- zzzzzzseg ends
- end Main
-